這邊是假設今天有個是要在玩家全部行動完畢時結束回合,而這邊會用Visitor獲取玩家單位的可行動數量+用Observer每次在控制狀態為等待輸入(CALWaitingForInputCellGridState
)觸發更新
Unit.cs
public virtual void RunVisitor(IUnitVisitor unitVisitor)
{
unitVisitor.VisitUnit(this);
}
UnitSystem.cs
using LinXuan.Common.Main;
using LinXuan.Common.Misc;
using LuLuBearStudio.Characters;
using System.Collections.Generic;
namespace LinXuan.TBSF.Misc
{
public class UnitSystem : IGameSystem
{
private CellGrid m_CellGrid;
private List<Unit> m_PlayerUnits = new List<Unit>();
private List<Unit> m_EnemyUnits = new List<Unit>();
private List<Unit> m_AllUnits = new List<Unit>();
public List<Unit> PlayableUnit { get; private set; }
public UnitSystem(CellGrid cellGrid)
{
m_CellGrid = cellGrid;
Initialize();
}
public void Initialize()
{
}
public void Initialize(List<Unit> units)
{
m_AllUnits = units;
m_PlayerUnits.AddRange(m_AllUnits.FindAll(u => u is IPlayer));
m_EnemyUnits.AddRange(m_AllUnits.FindAll(u => u is IEnemy));
}
public void RunVisitor(IUnitVisitor unitVisitor)
{
foreach (Unit unit in m_AllUnits)
unit.RunVisitor(unitVisitor);
}
}
}
IUnitVisitor.cs
using LuLuBearStudio.Characters;
namespace LinXuan.Common.Misc
{
public abstract class IUnitVisitor
{
public virtual void VisitUnit(Unit unit)
{
}
public virtual void VisitPlayerUnit(IPlayer player)
{
VisitUnit(player);
}
public virtual void VisitEnemyUnit(IEnemy enemy)
{
VisitUnit(enemy);
}
}
}
UnitInfoVisitor.cs
using Assets.Scripts.GUI.GUITool;
using LinXuan.Common.Misc;
using LuLuBearStudio.CALAbilities;
using LuLuBearStudio.Characters;
namespace LinXuan.TBSF.Misc
{
public class UnitInfoVisitor : IUnitVisitor
{
public int UnitCount { get; private set; }
public int PlayerCount { get; private set; }
public int EnemyCount { get; private set; }
public int UseableUnitCount { get; private set; }
public int MovableUnitCount { get; private set; }
public int AttackableUnitCount { get; private set; }
public override void VisitUnit(Unit unit)
{
base.VisitUnit(unit);
UnitCount++;
if (unit as IPlayer)
VisitPlayerUnit(unit as IPlayer);
}
public override void VisitPlayerUnit(IPlayer player)
{
AbilityEditor abilityEditor = player.AbilityEditor;
if (abilityEditor.CanPerform(UIInputObserver.CellGrid))
{
UseableUnitCount++;
}
PlayerCount++;
}
public void VisitorReset()
{
EnemyCount = 0;
UnitCount = 0;
UseableUnitCount = 0;
}
}
}
IGameEventObserver.cs
namespace LinXuan.Common.GameEvent
{
public interface IGameEventObserver
{
void SetSubject(IGameEventSubject subject);
void ObserverUpdate();
}
}
UnitUseAbilityObserverGUI.cs
using LinXuan.Common.GameEvent;
using TbsFramework.Grid;
namespace LinXuan.TBSF.GameEvent
{
public class UnitUseAbilityObserverGUI : IGameEventObserver
{
private UseableUnitCountSubject m_UseableUnitCountSubject = null;
private CellGrid m_CellGrid = null;
public UnitUseAbilityObserverGUI(CellGrid cellGrid)
{
m_CellGrid = cellGrid;
}
public void ObserverUpdate()
{
m_CellGrid.UseableUnitCountGUIUpdate();
}
public void SetSubject(IGameEventSubject subject)
{
m_UseableUnitCountSubject = subject as UseableUnitCountSubject;
}
}
}
UseableUnitCountSubject.cs
namespace LinXuan.Common.GameEvent
{
public class UseableUnitCountSubject : IGameEventSubject
{
public UnitCountEventArgs UnitCountEventArgs { get; private set; }
public override void SetParameter(object parameter)
{
Notify();
}
}
}
CALWaitingForInputCellGridState.cs
using Assets.Scripts.GUI.GUITool;
using LuLuBearStudio.CALAbilities;
using System.Collections.Generic;
namespace Assets.Scripts.TBS_Framework_extends.CellGridStates
{
public class CALWaitingForInputCellGridState : CellGridState
{
...
public override void OnStateEnter()
{
base.OnStateEnter();
UIInputObserver.IsPlayerCanInput = true;
foreach (Unit unit in units)
{
AbilityEditor abilityEditor = unit.GetComponent<AbilityEditor>();
var canPerformAction = abilityEditor.CanPerform(_cellGrid);
if (!canPerformAction)
{
unit.SetState(new UnitStateMarkedAsFinished(unit));
}
else
{
unit.SetState(new UnitStateNormal(unit));
}
}
UIInputObserver.CellGrid.NotifyGameEvent(LinXuan.TBSF.Enums.GameEventType.GetUseableUnitCount, null);
}
...
}
}
CellGrid.cs
public event EventHandler UseableUnitCountUpdate;
private UnitSystem m_UnitSystem;
private void Awake()
{
m_UnitSystem = new UnitSystem(this);
}
private void Initialize()
{
...
m_UnitSystem.Initialize(Units);
}
public void RunUnitVisitor(IUnitVisitor unitVisitor)
{
m_UnitSystem.RunVisitor(unitVisitor);
}
public void UseableUnitCountGUIUpdate()
{
UseableUnitCountUpdate.Invoke(this, null);
}
CALGUIController.cs
private UnitInfoVisitor m_UnitInfoVisitor = new UnitInfoVisitor();
private void Awake()
{
CellGrid.UseableUnitCountUpdate += ShowUseableUnitCount;
}
private void Start()
{
CellGrid.RegisterGameEvent(LinXuan.TBSF.Enums.GameEventType.GetUseableUnitCount, new UnitUseAbilityObserverGUI(UIInputObserver.CellGrid));
}
...
private void ShowUseableUnitCount(object sender, EventArgs e)
{
m_UnitInfoVisitor.VisitorReset();
CellGrid.RunUnitVisitor(m_UnitInfoVisitor);
int useableCount = m_UnitInfoVisitor.UseableUnitCount;
Debug.Log("Useable count " + useableCount);
}
這邊當角色還沒消耗完行動次數時,就會顯示可行動人數為兩人
而要是有單位消耗完行動次數後,數字就會相應減少
老實說寫起來有點繞一大圈的感覺,好處大概就是需要重新計算的時候在去做重新讀一次陣列的行為,不用每次都跑一次全部的陣列讀目前狀態,在陣列數量大的時候應該會更有感覺點
設計模式與遊戲開發的完美結合(暢銷回饋版)
Turn Based Strategy Framework
流離之歌